# -*- coding: utf-8 -*-

import configparser
import logging
import os
import sys

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from podifan_low import test_stock as test_stock_low


config = configparser.ConfigParser()
config_file = 'config.ini'
if not os.path.exists(config_file):
    raise FileNotFoundError(f"Configuration file '{config_file}' not found.")


config.read(config_file)
DATA_DIR = config['DEFAULT'].get('DataDir', 'd:/Python/study_data')
LIST_DIR = config['DEFAULT'].get('List', 'list')
LOG_FILE = config['DEFAULT'].get('LogFile_Podifan', 'log_podifan.txt')

if not os.path.exists(DATA_DIR):
    os.makedirs(DATA_DIR)

filelog = True
logger = logging.getLogger('log')
logger.setLevel(logging.DEBUG)
while logger.hasHandlers():
    for i in logger.handlers:
        logger.removeHandler(i)
# file log
# formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
formatter = logging.Formatter('%(message)s')

if filelog:
    fh = logging.FileHandler(LOG_FILE, encoding='utf-8')
    fh.setLevel(logging.DEBUG)
    fh.setFormatter(formatter)
    logger.addHandler(fh)

# console log
# formatter = logging.Formatter('%(message)s')
# ch = logging.StreamHandler(sys.stdout)
# ch.setLevel(logging.DEBUG)
# ch.setFormatter(formatter)
# logger.addHandler(ch)


def test_all_stocks(folder):
    hold_5_days = []
    hold_10_days = []
    hold_20_days = []
    hold_30_days = []
    hold_60_days = []
    for file in os.listdir(folder):
        if file.endswith('.csv'):
            path = os.path.join(folder, file)
            result = test_stock(path)
            hold_5_days.append(result[0])
            hold_10_days.append(result[1])
            hold_20_days.append(result[2])
            hold_30_days.append(result[3])
            hold_60_days.append(result[4])

    print(f"Average return for holding 5 days: {np.mean(hold_5_days):.4f}")
    print(f"Average return for holding 10 days: {np.mean(hold_10_days):.4f}")
    print(f"Average return for holding 20 days: {np.mean(hold_20_days):.4f}")
    print(f"Average return for holding 30 days: {np.mean(hold_30_days):.4f}")
    print(f"Average return for holding 60 days: {np.mean(hold_60_days):.4f}")


def test_stock(path, name):
    """
    Parameters:
    path (str): The file path to the stock data CSV file.

    Returns:
    None
    """
    # 获取股票数据
    data = pd.read_csv(path, parse_dates=['date'])

    # 获取股票数据
    data = pd.read_csv(path)

    # 确保索引是日期时间类型
    if 'date' in data.columns:
        data.index = pd.to_datetime(data.date)
    else:
        raise ValueError("The 'date' column is missing from the data.")

    # 确保索引是日期时间类型
    data.index = pd.to_datetime(data.date)

    # 计算5日均线
    data['5_day_mavg'] = data['close'].rolling(window=5).mean()
    data['10_day_mavg'] = data['close'].rolling(window=10).mean()
    data['20_day_mavg'] = data['close'].rolling(window=20).mean()

    data['5_day_min'] = data['close'].rolling(window=5).min()
    data['10_day_min'] = data['close'].rolling(window=10).min()
    data['20_day_min'] = data['close'].rolling(window=20).min()
    data['60_day_min'] = data['close'].rolling(window=60).min()

    data['10_day_max'] = data['close'].rolling(window=10).max()
    data['90_day_max'] = data['close'].rolling(window=90).max()
    # data['falling_trend'] = (
    #         (data['5_day_mavg'] < data['20_day_mavg']) &
    #         (data['5_day_mavg'].shift(1) < data['20_day_mavg'].shift(1)) &
    #         (data['5_day_mavg'].shift(2) < data['20_day_mavg'].shift(2)) &
    #         (data['5_day_mavg'].shift(3) < data['20_day_mavg'].shift(3)) &
    #         (data['5_day_mavg'].shift(4) < data['20_day_mavg'].shift(4)) &
    #         (data['5_day_mavg'].shift(5) < data['20_day_mavg'].shift(5)) &
    #         (data['5_day_mavg'].shift(6) < data['20_day_mavg'].shift(6)) &
    #         (data['5_day_mavg'].shift(7) < data['20_day_mavg'].shift(7)) &
    #         (data['5_day_mavg'].shift(8) < data['20_day_mavg'].shift(8)) &
    #         (data['5_day_mavg'].shift(9) < data['20_day_mavg'].shift(9)) &
    #         (data['5_day_mavg'].shift(10) < data['20_day_mavg'].shift(10)) &
    #         (data['5_day_mavg'].shift(11) < data['20_day_mavg'].shift(11)) &
    #         (data['5_day_mavg'].shift(12) < data['20_day_mavg'].shift(12)) &
    #         (data['5_day_mavg'].shift(13) < data['20_day_mavg'].shift(13)) &
    #         (data['5_day_mavg'].shift(14) < data['20_day_mavg'].shift(14)) &
    #         (data['5_day_mavg'].shift(15) < data['20_day_mavg'].shift(15)) &
    #         (data['5_day_mavg'].shift(16) < data['20_day_mavg'].shift(16)) &
    #         (data['5_day_mavg'].shift(17) < data['20_day_mavg'].shift(17)) &
    #         (data['5_day_mavg'].shift(18) < data['20_day_mavg'].shift(18)) &
    #         (data['5_day_mavg'].shift(19) < data['20_day_mavg'].shift(19)) &
    #         (data['5_day_mavg'].shift(20) < data['20_day_mavg'].shift(20)) &
    #         (data['10_day_min'] < data['90_day_max'] * 0.8)
    # ) | (
    #         (data['5_day_mavg'] < data['20_day_mavg']) &
    #         (data['5_day_mavg'].shift(1) < data['20_day_mavg'].shift(1)) &
    #         (data['5_day_mavg'].shift(2) < data['20_day_mavg'].shift(2)) &
    #         (data['5_day_mavg'].shift(3) < data['20_day_mavg'].shift(3)) &
    #         (data['5_day_mavg'].shift(4) < data['20_day_mavg'].shift(4)) &
    #         (data['5_day_mavg'].shift(5) < data['20_day_mavg'].shift(5)) &
    #         (data['5_day_mavg'].shift(6) < data['20_day_mavg'].shift(6)) &
    #         (data['5_day_mavg'].shift(7) < data['20_day_mavg'].shift(7)) &
    #         (data['5_day_mavg'].shift(8) < data['20_day_mavg'].shift(8)) &
    #         (data['5_day_mavg'].shift(9) < data['20_day_mavg'].shift(9)) &
    #         (data['5_day_mavg'].shift(10) < data['20_day_mavg'].shift(10)) &
    #         (data['5_day_mavg'].shift(11) < data['20_day_mavg'].shift(11)) &
    #         (data['5_day_mavg'].shift(12) < data['20_day_mavg'].shift(12)) &
    #         (data['5_day_mavg'].shift(13) < data['20_day_mavg'].shift(13)) &
    #         (data['5_day_mavg'].shift(14) < data['20_day_mavg'].shift(14)) &
    #         (data['5_day_mavg'].shift(15) < data['20_day_mavg'].shift(15)) &
    #         (data['10_day_min'] < data['90_day_max'] * 0.75)
    # ) | (
    #         (data['5_day_mavg'] < data['10_day_mavg']) & (data['10_day_mavg'] < data['20_day_mavg']) &
    #         (data['5_day_mavg'].shift(1) < data['10_day_mavg'].shift(1)) & (data['10_day_mavg'].shift(1) < data['20_day_mavg'].shift(1)) &
    #         (data['5_day_mavg'].shift(2) < data['10_day_mavg'].shift(2)) & (data['10_day_mavg'].shift(2) < data['20_day_mavg'].shift(2)) &
    #         (data['5_day_mavg'].shift(3) < data['10_day_mavg'].shift(3)) & (data['10_day_mavg'].shift(3) < data['20_day_mavg'].shift(3)) &
    #         (data['5_day_mavg'].shift(4) < data['10_day_mavg'].shift(4)) & (data['10_day_mavg'].shift(4) < data['20_day_mavg'].shift(4)) &
    #         (data['5_day_mavg'].shift(5) < data['10_day_mavg'].shift(5)) & (data['10_day_mavg'].shift(5) < data['20_day_mavg'].shift(5)) &
    #         (data['5_day_mavg'].shift(6) < data['10_day_mavg'].shift(6)) & (data['10_day_mavg'].shift(6) < data['20_day_mavg'].shift(6)) &
    #         (data['5_day_mavg'].shift(7) < data['10_day_mavg'].shift(7)) & (data['10_day_mavg'].shift(7) < data['20_day_mavg'].shift(7)) &
    #         (data['5_day_mavg'].shift(8) < data['10_day_mavg'].shift(8)) & (data['10_day_mavg'].shift(8) < data['20_day_mavg'].shift(8)) &
    #         (data['5_day_mavg'].shift(9) < data['10_day_mavg'].shift(9)) & (data['10_day_mavg'].shift(9) < data['20_day_mavg'].shift(9)) &
    #         (data['5_day_mavg'].shift(10) < data['10_day_mavg'].shift(10)) & (data['10_day_mavg'].shift(10) < data['20_day_mavg'].shift(10)) &
    #         (data['10_day_min'] < data['90_day_max'] * 0.9)
    # )
    data['falling_trend'] = (data['10_day_min'] == data['60_day_min']) & ((data['10_day_min'] < data['90_day_max'] * 0.8))

    # 寻找放量阳线
    data['5_day_avg_volume'] = data['volume'].rolling(window=5).mean()
    data['10_day_avg_volume'] = data['volume'].rolling(window=10).mean()
    data['bullish_volume'] = (data['close'].pct_change() >= 0.07) & data['falling_trend']

    # 生成买入信号
    data['close_to_20_day_mavg'] = np.isclose(data['close'], data['20_day_mavg'], atol=0.03 * data['20_day_mavg']) & (data['close'] > data['20_day_min'].shift(1))
    data['close_to_10_day_mavg'] = np.isclose(data['close'], data['10_day_mavg'], atol=0.02 * data['10_day_mavg']) & (data['close'] > data['20_day_min'].shift(1))
    data['close_to_20_day_min'] = np.isclose(data['close'], data['20_day_min'], atol=0.05 * data['20_day_min']) & (data['close'] > data['20_day_min'].shift(1))

    data['back_test'] = (
            (data['bullish_volume'].shift(2, fill_value=False) & (data['close'].shift(1).pct_change() > -0.06)) |
            (data['bullish_volume'].shift(3, fill_value=False) & (data['close'].shift(2).pct_change() > -0.06)) |
            (data['bullish_volume'].shift(4, fill_value=False) & (data['close'].shift(3).pct_change() > -0.06)) |
            (data['bullish_volume'].shift(5, fill_value=False) & (data['close'].shift(4).pct_change() > -0.06)) |
            (data['bullish_volume'].shift(6, fill_value=False) & (data['close'].shift(5).pct_change() > -0.06)) |
            (data['bullish_volume'].shift(7, fill_value=False) & (data['close'].shift(6).pct_change() > -0.06)) |
            (data['bullish_volume'].shift(8, fill_value=False) & (data['close'].shift(7).pct_change() > -0.06)) |
            (data['bullish_volume'].shift(9, fill_value=False) & (data['close'].shift(8).pct_change() > -0.06)) |
            (data['bullish_volume'].shift(10, fill_value=False) & (data['close'].shift(9).pct_change() > -0.06)) |
            (data['bullish_volume'].shift(11, fill_value=False) & (data['close'].shift(10).pct_change() > -0.06))
                                ) & (data['close'] == data['5_day_min'])

data['buy_signal'] = (data['back_test'] & ~(data['back_test'].shift(1) | data['back_test'].shift(2) | data['back_test'].shift(3) | data['back_test'].shift(4) | data['back_test'].shift(5) | data['back_test'].shift(6) | data['back_test'].shift(7) | data['back_test'].shift(8) | data['back_test'].shift(9) | data['back_test'].shift(10)))
    # 检查生成的买入信号日期
    buy_signal_dates = data[data['buy_signal']].index
    # print(f"Buy signal dates: {buy_signal_dates}")
    dict = {}
    dict[os.path.basename(path).split('.')[0]] = [str(date)[:10] for date in buy_signal_dates]
    # print(dict)
    # data.to_csv(r'd:\Python\study_data\code_DataFrame.csv')
    return dict


def find_all_buys(path):
    all_buys_code = {}
    all_buys_name = {}
    list_df = pd.read_csv(f'{LIST_DIR}/stocks.csv')
    stocks = dict(zip(list_df['名称'], list_df['代码']))
    for name, code in stocks.items():
        if 'ST' not in name:
            try:
                buys = test_stock(f'{DATA_DIR}/{path}/{code}.csv', name)
                # buys_ = test_stock_low(f'{DATA_DIR}/{path}/{code}.csv', name)
                # for k1, v1 in buys.items():
                #     for k2, v2 in buys_.items():
                #         if k1 == k2:
                #             buys[k1] = list(set(v1) | set(v2))
                for key, value in buys.items():
                    for date in value:
                        if date in all_buys_code:
                            all_buys_code[date].append(key)
                            all_buys_name[date].append(name)
                        else:
                            all_buys_code[date] = [key]
                            all_buys_name[date] = [name]
            except FileNotFoundError:
                continue

    all_buys_code_df = pd.DataFrame.from_dict(all_buys_code, orient='index').sort_index()
    all_buys_name_df = pd.DataFrame.from_dict(all_buys_name, orient='index').sort_index()
    all_buys_code_df.to_csv('all_buys_20_day_line.csv')
    all_buys_name_df.to_csv('all_buys_20_day_line_name.csv')


if __name__ == '__main__':
    find_all_buys('stocks_test2')
    # find_all_buys('stocks')
